#include <stdio.h>
#include <stdlib.h>
#include <string.h>

//重要结论: 当数组名做函数参数时, 实际传递给函数的是一个指向数组第一个元素的指针
//数组做函数参数时, 形参类型应该定义为数组第一个元素的指针类型

//可读性 要比效率更重要
//void printArray(int *arr, int len) 这个地方一般第一眼是传int类型的地址, 第二眼才想到传一个数组指针
void printArray(int arr[], int len)
{
    for (int i = 0; i < len; ++i){
        printf("%d ", arr[i]);
        printf("%d ", *(arr+i));
    }
}

void test01()
{
    int arr[10] = { 1, 2, 3, 4 };

    //1.sizeof    2.对数组名取地址
    //以上两种情况,数组名不是指向首元素的指针
    //以上两种情况,数组名是数组类型
    //! 除了以上两点之外, 数组名在其他任何情况下都是指向数组首元素的指针

    printf("sizeof arr:%d\n", sizeof(arr));

    printf("&arr addr:%d\n", &arr);
    printf("&arr+1 addr:%d\n", &arr+1);

    int *p = arr;

    //数组名是一个常量指针
    //arr = NULL;  常量指针不能修改

    //数组下标能否是负数? 
    p += 3;
    printf("p[-1]:%d\n",  p[-1]);
    printf("p[-1]:%d\n", *(p-1));

    //数组指针类型和数组首元素指针类型
}

//数组指针意思是指向整个数组的指针
//如何定义一个可以指向数组的指针
void test02()
{
    int arr[5] = { 1, 2, 3, 4 };
    &arr;
    
    //1.先定义数组类型,再定义数组指针类型
    typedef int (ARRAY_TYPE)[5];    //typedef unsigned int u32

    ARRAY_TYPE myarray; // int myarray[5]
    for (int i = 0; i < 5; ++i){
        myarray[i] = 100 + i;
    }
    
    for (int i = 0; i < 5; ++i){
        printf("%d ", myarray[i]);
    }
    printf("\n");
    
    //对数组名取地址代表指向整个数组的指针
    ARRAY_TYPE *pArray = &arr;

    //1.1   pArray指针指向的整个数组
    //1.2   那么*pArray类型就是数组,也就是数组名指向首元素类型的指针

    printf("*(*pArray+1) = %d\n", *(*pArray+1));

    //2. 直接定义数组指针类型
    typedef int(*ARRAY_POINTER)[5];
    ARRAY_POINTER pArr = &arr;

    //3. 直接定义数组指针变量
    int(*pArrParam)[5] = &arr;
    
}

int main(int argc, char const *argv[])
{
    test01();
    test02();
    return 0;
}
